package com.genreate;

import com.common.entity.CClass;
import com.common.entity.CField;
import com.common.entity.CMethod;
import com.sqlsession.database.CColumn;
import com.sqlsession.database.CTable;
import com.common.util.ParamUtil;
import com.common.util.TypeUtils;
import com.sqlsession.database.DbType;

import java.util.*;

public class CTableToClass {

    public static CClass getClassByCTable(CTable cTable) {
        DbType dbType = cTable.getDbType();

        CClass cClass = new CClass(cTable);
        String name = cTable.getName();
        cClass.setName(ParamUtil.getClassName(name));
        cClass.setcFields(getcFields(cTable));
        Map<String, Map<String, String>> annotations = new HashMap<>();

        StringBuilder builder = new StringBuilder();
        builder.append("value=");

        builder.append("\"").append(dbType.formatName(name)).append("\"").append(",").append("keepGlobalPrefix = true");

        Map<String, String> annotation = new HashMap<>();
        // TODO: 2023-03-11
        annotation.put("com.baomidou.mybatisplus.annotation.TableName", builder.toString());
        annotations.put("@TableName", annotation);
        cClass.setAnnotations(annotations);

        cClass.setcMethods(getMethods(cClass));
        cClass.setCommon(cTable.getCommon());
        return cClass;
    }

    private static List<CField> getcFields(CTable cTable) {
        DbType dbType = cTable.getDbType();
        List<CField> cFields = new LinkedList<>();
        List<CColumn> cColumns = cTable.getcColumns();
        CField cField;
        for (CColumn cColumn : cColumns) {
            cField = new CField();
            String name = cColumn.getName();
            String type = cColumn.getType();
            boolean key = cColumn.isPrimaryKey();
            String common = cColumn.getCommon();
            cField.setCommon(common);
            System.out.println(cColumn.getcTable().getName() + "-------------" + name);
            cField.setName(ParamUtil.getClassFiledName(name));
            cField.setModifier("private");
            Map<String, Map<Set<String>, String>> map = new HashMap<>();

            Map<Set<String>, String> TableField = new HashMap<>();
            StringBuilder builder = new StringBuilder();

            builder.append("value=");
            builder.append("\"").append(dbType.formatName(name)).append("\"");
            Set<String> set = new HashSet<>();
            if (key) {
                builder.append(",").append("type = IdType.AUTO");
                set.add("com.baomidou.mybatisplus.annotation.TableId");
                set.add("com.baomidou.mybatisplus.annotation.IdType");
                TableField.put(set, builder.toString());
                map.put("@TableId", TableField);
            } else {
                set.add("com.baomidou.mybatisplus.annotation.TableField");
                TableField.put(set, "value = " + "\"" + dbType.formatName(name) + "\"");
                map.put("@TableField", TableField);
            }
            cField.setAnnotations(map);
            Map<String, String> classType = new HashMap<>();
            classType.put(TypeUtils.getJavaType(type), TypeUtils.getJavaTypePath(type));
            cField.setClassType(classType);
            cFields.add(cField);
        }
        return cFields;
    }

    private static List<CMethod> getMethods(CClass cClass) {
        List<CField> cFields = cClass.getcFields();
        if (cFields == null) {
            cFields = getcFields(cClass.getcTable());
            cClass.setcFields(cFields);
        }
        List<CMethod> cMethods = new LinkedList<>();
        CMethod cMethod;
        for (CField cField : cFields) {
            //get方法
            cMethod = new CMethod();
            String name = cField.getName();
            Map<String, String> classType = cField.getClassType();
            String type = "void";
            for (Map.Entry<String, String> entry : classType.entrySet()) {
                type = entry.getKey();
            }
            cMethod.setMethodName("public " + type + "  get" + ParamUtil.getClassMethdodName(name) + "()");
            cMethod.setBody("return this." + ParamUtil.getClassFiledName(name) + ";");
            cMethod.setReturnType(classType);
            cMethods.add(cMethod);

            //set方法
            cMethod = new CMethod();
            int i = 0;
            List<Map<String, Map<String, String>>> params = new LinkedList<>();
            Map<String, Map<String, String>> param = new HashMap<>();
            param.put(name, classType);
            params.add(param);
            cMethod.setParam(params);

            StringBuilder builder = new StringBuilder("public void set" + ParamUtil.getClassMethdodName(name));
            builder.append("(");
            builder.append(type).append(" ").append(ParamUtil.getClassFiledName(name));
            if (++i < params.size() - 1) {
                builder.append(",");
            }
            builder.append(")");
            cMethod.setMethodName(builder.toString());
            cMethod.setBody("this." + ParamUtil.getClassFiledName(name) + " = " + ParamUtil.getClassFiledName(name) + ";");
            cMethods.add(cMethod);
        }
        return cMethods;
    }
}
